// --------------------------------------------------------------------------------------------------------------------
// <copyright file="ValueExpiry.cs" company="XamlNinja">
//   2011 Richard Griffin and Ollie Riches
// </copyright>
// <summary>
// </summary>
// <credits>
// StuartHarris http://red-badger.com/Blog/post/Watching-Silverlight-Dependency-Properties-with-Reactive-Extensions.aspx#comment
// </credits>
// --------------------------------------------------------------------------------------------------------------------

namespace WP7Contrib.View.Controls.Behaviors
{
    using System;
    using System.Reactive;
    using System.Reactive.Disposables;
    using System.Reactive.Linq;
    using System.Windows;
    using System.Windows.Data;
    using System.Windows.Input;
    using System.Windows.Interactivity;

    using WP7Contrib.View.Controls.BindingListener;
    using WP7Contrib.View.Controls.Extensions;

    public class FrameworkElementClickCommand : Behavior<FrameworkElement>
    {
        public static readonly DependencyProperty CommandBindingProperty = DependencyProperty.Register(
            "CommandBinding", 
            typeof(Binding), 
            typeof(FrameworkElementClickCommand), 
            new PropertyMetadata(CommandBindingChanged));

        private ICommand command;

        private CompositeDisposable subscriptions;

        public Binding CommandBinding
        {
            get
            {
                return (Binding)this.GetValue(CommandBindingProperty);
            }

            set
            {
                this.SetValue(CommandBindingProperty, value);
            }
        }

        protected override void OnAttached()
        {
            base.OnAttached();

            Observable.FromEventPattern(
                (EventHandler<RoutedEventArgs> h) => new RoutedEventHandler(h), 
                handler => this.AssociatedObject.Loaded += handler, 
                handler => this.AssociatedObject.Loaded -= handler).Subscribe(@event => this.Bind());
            Observable.FromEventPattern(
                (EventHandler<RoutedEventArgs> h) => new RoutedEventHandler(h), 
                handler => this.AssociatedObject.Unloaded += handler, 
                handler => this.AssociatedObject.Unloaded -= handler).Subscribe(@event => this.UnBind());
        }

        private static void CommandBindingChanged(
            DependencyObject dependencyObject, DependencyPropertyChangedEventArgs args)
        {
            var @this = dependencyObject as FrameworkElementClickCommand;
            if (@this != null)
            {
                @this.CommandBindingChanged();
            }
        }

        private void Bind()
        {
            this.subscriptions = new CompositeDisposable
                {
                   this.AssociatedObject.GetClick().Subscribe(this.OnNextClick) 
                };

            this.BindCommand();
        }

        private void BindCommand()
        {
            Binding binding = this.CommandBinding;
            if (binding != null)
            {
                this.subscriptions.Add(
                    this.AssociatedObject.GetChanges(binding).Subscribe(
                        args => this.command = args.NewValue as ICommand));
            }
        }

        private void CommandBindingChanged()
        {
            if (this.AssociatedObject != null)
            {
                this.BindCommand();
            }
        }

        private void OnNextClick(EventPattern<EventArgs> @event)
        {
            if (this.command != null)
            {
                this.command.Execute(null);
            }
        }

        private void UnBind()
        {
            if (this.subscriptions != null)
            {
                this.subscriptions.Dispose();
            }
        }
    }
}